#!/usr/bin/env python

import SocketServer
import threading

from constants import *

class ChatServer(object):
    def __init__(self):
        #self.N = 0
        self.freeUserID = 0
        #self.events = []
        self.userNames = set()
        self.users = {}

    def process(self, request, client_address):
        data = request[0]
        socket = request[1]

        if data == '':
            print "EMPTY MSG FROM", client_address[0]
            return

        splitted_data = data.split()
        cmd = int(splitted_data[0])
        
        if cmd == LOGIN_CODE:
            self.login(splitted_data[1], socket, client_address)

        elif cmd == LOGOUT_CODE:
            self.logout(int(splitted_data[1]))

        elif cmd == MSG_TO_SERVER_CODE:
            self.msg(int(splitted_data[1]), data, socket, client_address)
            pass
        else:
            #TODO: bad command. Do something
            print "WRONG COMMAND:", data

    def login(self, name, socket, client_address):
        if name not in self.userNames:
            self.userNames.add(name)
            id = self.freeUserID
            self.freeUserID += 1
            self.users[id] = (name, client_address)
            socket.sendto(str(LOGIN_SUCCESSFUL_CODE) + " " + str(id), client_address)
            print "LOGIN:" + name
        else:
            socket.sendto(str(BUSY_NAME_CODE), client_address)


    def logout(self, id):

        if id in self.users:
            name = self.users[id][0]
            self.userNames.remove(name)
            del self.users[id]
            print "LOGOUT:" + name

    def msg(self, id, data, socket, client_address):

        #wrong client id
        if id not in self.users:
            socket.sendto(str(WRONG_ID_CODE) + ' ' + str(id), client_address)
            return

        #to skip service symbols
        indent = len(str(MSG_TO_SERVER_CODE)) + len(str(id)) + 2 * len(' ')

        #msg = username: text
        msg = self.users[id][0] + ": " + data[indent:]

        addressList = [ usr[1] for usr in self.users.values()]

        #resend this message to everyone
        self.sendMsgToClient(msg, addressList, socket)

    def sendMsgToClient(self, msg, addressList, socket):

        #send this message to everyone
        for addr in addressList:
            socket.sendto(msg, addr)


chatServer = ChatServer()

class MyUDPHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        global chatServer

        chatServer.process(self.request, self.client_address)


"""
class MyUDPHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        data = self.request[0].strip()
        socket = self.request[1]
        print "{} wrote:".format(self.client_address[0])
        print data
        socket.sendto("YOUR SENT ME: " + data, self.client_address)
"""

if __name__ == "__main__":
    server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler)
    server.serve_forever()

    # Create the server, binding to HOST on port PORT
#server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)

    #infinity loop
#server.serve_forever()
